<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/blogs/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/blogs/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/blogs/css/main.css?v=5.1.3" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/blogs/images/apple-touch-icon.png?v=5.1.3">


  <link rel="icon" type="image/png" sizes="32x32" href="/blogs/images/favicon-32x32.png?v=5.1.3">


  <link rel="icon" type="image/png" sizes="16x16" href="/blogs/images/favicon-16x16.png?v=5.1.3">


  <link rel="mask-icon" href="/blogs/images/logo.svg?v=5.1.3" color="#222">





  <meta name="keywords" content="Node.js," />










<meta name="description" content="Express之中间件（笔记）中间件有什么用？  中间件用于业务流程的中间处理环节 中间件必须具备输入和输出，上一级的输出作为下一级的输入  1.Express中间件的调用流程当一个请求到达Express的服务器之后，可以连续调用多个中间件，从而对这次请求进行预处理（中间件的作用）。 流程如下：   中间件处理完成之后，再交给路由，然后响应到客户端 2.Express中间件的格式Express的中">
<meta property="og:type" content="article">
<meta property="og:title" content="express之中间件">
<meta property="og:url" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/index.html">
<meta property="og:site_name" content="Chao&#39;s blog">
<meta property="og:description" content="Express之中间件（笔记）中间件有什么用？  中间件用于业务流程的中间处理环节 中间件必须具备输入和输出，上一级的输出作为下一级的输入  1.Express中间件的调用流程当一个请求到达Express的服务器之后，可以连续调用多个中间件，从而对这次请求进行预处理（中间件的作用）。 流程如下：   中间件处理完成之后，再交给路由，然后响应到客户端 2.Express中间件的格式Express的中">
<meta property="og:locale">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middleware.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middleware_1.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middle_next.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middle_fun.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middle_func.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/error.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/error_catch.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman1.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman2.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman3.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman4.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman5.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman6.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman7.png">
<meta property="og:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman8.png">
<meta property="article:published_time" content="2022-04-25T14:39:09.000Z">
<meta property="article:modified_time" content="2022-04-26T15:07:45.988Z">
<meta property="article:author" content="Chaoyxy">
<meta property="article:tag" content="Node.js">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middleware.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '',
    scheme: 'Gemini',
    version: '5.1.3',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":true,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://louchaoyy.gitee.io/blogs/2022/04/25/express之中间件/"/>





  <title>express之中间件 | Chao's blog</title>
  








<meta name="generator" content="Hexo 5.4.0"></head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blogs/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">Chao's blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blogs/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-question-circle"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/blogs/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-question-circle"></i> <br />
            
            关于
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/blogs/tags" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-question-circle"></i> <br />
            
            标签
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://louchaoyy.gitee.io/blogs/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/blogs/images/cat.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Chao's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">express之中间件</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2022-04-25T22:39:09+08:00">
                2022-04-25
              </time>
            

            

            
          </span>

          

          
            
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count disqus-comment-count"
                        data-disqus-identifier="2022/04/25/express之中间件/" itemprop="commentCount"></span>
                </a>
              </span>
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="Express之中间件（笔记）"><a href="#Express之中间件（笔记）" class="headerlink" title="Express之中间件（笔记）"></a>Express之中间件（笔记）</h1><p>中间件有什么用？</p>
<ul>
<li>中间件用于业务流程的中间处理环节</li>
<li>中间件必须具备<strong>输入</strong>和<strong>输出</strong>，上一级的输出作为下一级的输入</li>
</ul>
<h2 id="1-Express中间件的调用流程"><a href="#1-Express中间件的调用流程" class="headerlink" title="1.Express中间件的调用流程"></a>1.Express中间件的调用流程</h2><p>当一个请求到达Express的服务器之后，可以连续调用多个中间件，从而对这次请求进行<strong>预处理</strong>（中间件的作用）。</p>
<p>流程如下：</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middleware.png" class title="中间件的流程图">

<p>中间件处理完成之后，再交给路由，然后响应到客户端</p>
<h2 id="2-Express中间件的格式"><a href="#2-Express中间件的格式" class="headerlink" title="2.Express中间件的格式"></a>2.Express中间件的格式</h2><p>Express的中间件，本质上就是一个<strong>function处理函数</strong>，Express中间件的格式如下：</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middleware_1.png" class title="中间件的格式">

<p>中间件处理函数，第一部分是请求方式，第二个是路由，第三部分是一个回调函数（具备三个参数，第一个请求参数，第二个响应参数，第三个是next参数）</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 中间件处理函数</span></span><br><span class="line">app.get(<span class="string">&#x27;/getInfo&#x27;</span>,<span class="function">(<span class="params">req,res,next</span>)=&gt;</span>&#123;</span><br><span class="line">    next();</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>区别：路由的处理函数中参数只有req,res，中间件的处理函数参数req,res,next，<strong>且next是必须的</strong>。</p>
<span id="more"></span>

<h2 id="3-next函数的作用"><a href="#3-next函数的作用" class="headerlink" title="3.next函数的作用"></a>3.next函数的作用</h2><p><strong>next函数</strong>是<strong>实现多个中间件连续调用的关键</strong>，它表示把流转关系转交给下一个中间件或者路由</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middle_next.png" class title="中间件的作用">

<h2 id="4-定义中间件函数"><a href="#4-定义中间件函数" class="headerlink" title="4.定义中间件函数"></a>4.定义中间件函数</h2><p>定义一个最简单的中间件函数</p>
<p>中间件函数处理完，调用next()函数</p>
<p>表示把流转关系转交给下一个中间件或者路由</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 中间件函数</span></span><br><span class="line"><span class="comment">// 常量nw所指向的就是一个中间件函数</span></span><br><span class="line"><span class="keyword">const</span> mw = <span class="function"><span class="keyword">function</span>(<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;这是一个中间件函数！&quot;</span>);</span><br><span class="line">    <span class="comment">// 中间件函数处理完，调用next()函数</span></span><br><span class="line">    <span class="comment">// 表示把流转关系转交给下一个中间件或者路由</span></span><br><span class="line">    next();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="5-全局生效的中间件"><a href="#5-全局生效的中间件" class="headerlink" title="5.全局生效的中间件"></a>5.全局生效的中间件</h2><p>客户端发起的任何请求，到达服务器忠厚，都会触发的中间件，叫做全局生效的中间件</p>
<p>如何定义一个全局生效的中间件？</p>
<p>通过<code>app.use(中间件函数)</code>，即可定义有一个全局生效的中间件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> mw = <span class="function"><span class="keyword">function</span>(<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;这是一个中间件函数！&quot;</span>);</span><br><span class="line">    <span class="comment">// 中间件函数处理完，调用next()函数</span></span><br><span class="line">    <span class="comment">// 表示把流转关系转交给下一个中间件或者路由</span></span><br><span class="line">    next();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 注册为全局生效的中间件</span></span><br><span class="line">app.use(mw);</span><br></pre></td></tr></table></figure>

<p>这样，每一个请求到达服务器，先经过app.use这里，然后往mw这个函数去处理，处理完成再去找路由。</p>
<p>在这里，我们定义了一个最简单的中间件函数mw，然后注册了这个中间件函数，紧接着定义了两个路由，在postman发起两次请求，会是怎样的结果呢？</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 中间件函数</span></span><br><span class="line"><span class="comment">// 常量nw所指向的就是一个中间件函数</span></span><br><span class="line"><span class="keyword">const</span> mw = <span class="function"><span class="keyword">function</span>(<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;这是一个中间件函数！&quot;</span>);</span><br><span class="line">    <span class="comment">// 中间件函数处理完，调用next()函数</span></span><br><span class="line">    <span class="comment">// 表示把流转关系转交给下一个中间件或者路由</span></span><br><span class="line">    next();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 注册为全局生效的中间件</span></span><br><span class="line">app.use(mw);</span><br><span class="line"></span><br><span class="line">app.get(<span class="string">&#x27;/&#x27;</span>,<span class="function">(<span class="params">req,res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;调用了 / 路由&quot;</span>);</span><br><span class="line">    res.send(<span class="string">&#x27;Home page&#x27;</span>);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.get(<span class="string">&#x27;/user&#x27;</span>,<span class="function">(<span class="params">req,res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;调用了 /user 路由&quot;</span>);</span><br><span class="line">    res.send(<span class="string">&#x27;User page&#x27;</span>);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>,<span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>结果如下：</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middle_fun.png" class title="中间件的打印顺序">

<p>很显然，这个执行顺序是这样的：</p>
<p>当客户端发起请求时，到了中间件处理函数，处理完了之后转到**”/“<strong>路由去处理，第二次发起请求时，依然先执行中间件，然后转到</strong>/user**去处理。</p>
<h2 id="6-全局中间件的简化形式"><a href="#6-全局中间件的简化形式" class="headerlink" title="6.全局中间件的简化形式"></a>6.全局中间件的简化形式</h2><p>直接使用app.use(()=&gt;{})进行注册</p>
<p>同样的效果</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function">(<span class="params">req,res,next</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;这也是一个中间件函数！&quot;</span>);</span><br><span class="line">    next();</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h2 id="7-中间件的作用"><a href="#7-中间件的作用" class="headerlink" title="7.中间件的作用"></a>7.中间件的作用</h2><p><strong>中间件的作用是什么？</strong></p>
<p>在实际开发中，多个中间件是可以共享同一份<strong>req</strong>和<strong>res</strong>，基于这样的特性，我们可以在上游的中间件中，同意为<strong>req</strong>或<strong>res</strong>对象添加自定义的属性和方法，供下游的中间件和路由进行使用。</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/middle_func.png" class title="中间件的特性">

<p>如果我们做一个需求，假设每次一访问，我们都需要拿到访问服务器的时间。如果没有中间件，那么我们需要在每个路由里面获取时间，假如我们有了中间件，那么我们可以只写一次就行。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line">app.use(<span class="function">(<span class="params">req,res,next</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">// 获取到请求的时间</span></span><br><span class="line">    <span class="keyword">const</span> time = <span class="built_in">Date</span>.now();</span><br><span class="line">    <span class="comment">// 为req对象，挂载自定义属性，从而把时间共享给后面所有的路由</span></span><br><span class="line">    req.startTime = time;</span><br><span class="line">    next();</span><br><span class="line">&#125;)</span><br><span class="line">app.get(<span class="string">&#x27;/&#x27;</span>,<span class="function">(<span class="params">req,res</span>)=&gt;</span>&#123;</span><br><span class="line">    res.send(<span class="string">&#x27;Home page: &#x27;</span>+req.startTime);</span><br><span class="line">&#125;)</span><br><span class="line">app.get(<span class="string">&#x27;/user&#x27;</span>,<span class="function">(<span class="params">req,res</span>)=&gt;</span>&#123;</span><br><span class="line">    res.send(<span class="string">&#x27;User page: &#x27;</span>+req.startTime);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>,<span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>每次访问服务器，我们就能获取到改时间</p>
<p>eg</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Home page: 1650901677581</span><br><span class="line">User page: 1650901750292</span><br></pre></td></tr></table></figure>

<h2 id="8-连续定义多个全局中间件"><a href="#8-连续定义多个全局中间件" class="headerlink" title="8.连续定义多个全局中间件"></a>8.连续定义多个全局中间件</h2><p>可以使用app.use()连续定义多个全局中间件，客户端到达服务器之后哦，会按照中间件定义的顺序依次进行调用</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line">app.use(<span class="function">(<span class="params">req,res,next</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="comment">// 获取到请求的时间</span></span><br><span class="line">    <span class="keyword">const</span> time = <span class="built_in">Date</span>.now();</span><br><span class="line">    <span class="comment">// 为req对象，挂载自定义属性，从而把时间共享给后面所有的路由</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;第1个中间件！&quot;</span>);</span><br><span class="line">    req.startTime = time;</span><br><span class="line">    next();</span><br><span class="line">&#125;);</span><br><span class="line">app.use(<span class="function">(<span class="params">req,res,next</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;第2个中间件！&quot;</span>);</span><br><span class="line">    next();</span><br><span class="line">&#125;);</span><br><span class="line">app.get(<span class="string">&#x27;/&#x27;</span>,<span class="function">(<span class="params">req,res</span>)=&gt;</span>&#123;</span><br><span class="line">    res.send(<span class="string">&#x27;Home page: &#x27;</span>+req.startTime);</span><br><span class="line">&#125;)</span><br><span class="line">app.get(<span class="string">&#x27;/user&#x27;</span>,<span class="function">(<span class="params">req,res</span>)=&gt;</span>&#123;</span><br><span class="line">    res.send(<span class="string">&#x27;User page: &#x27;</span>+req.startTime);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>,<span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//发出一次请求之后（后台日志）</span></span><br><span class="line"><span class="comment">//第1个中间件！</span></span><br><span class="line"><span class="comment">//第2个中间件！</span></span><br></pre></td></tr></table></figure>

<h2 id="9-局部生效的中间件"><a href="#9-局部生效的中间件" class="headerlink" title="9.局部生效的中间件"></a>9.局部生效的中间件</h2><p>有时候，有些中间件不需要在全局使用，仅在局部使用即可。因此衍生了局部中间件。局部中间件就是不使用app.use注册的中间件，而是在路由里面使用的中间件。在路由模块下定义中间件，并且使用如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 路由模块</span></span><br><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 创建路由对象</span></span><br><span class="line"><span class="keyword">const</span> router =express.Router();</span><br><span class="line"><span class="keyword">const</span> mw1 = <span class="function"><span class="keyword">function</span>(<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;我是一个局部中间件！&quot;</span>);</span><br><span class="line">    next();</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// 挂载路由</span></span><br><span class="line">router.get(<span class="string">&#x27;/user/list&#x27;</span>,mw1,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    response.send(<span class="string">&#x27;Get user list.&#x27;</span>)</span><br><span class="line">&#125;);</span><br><span class="line">router.post(<span class="string">&#x27;/user/add&#x27;</span>,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    response.send(<span class="string">&#x27;Add new user&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 向外导出路由</span></span><br><span class="line"><span class="built_in">module</span>.exports = router</span><br></pre></td></tr></table></figure>

<p>这里的mw1就是局部中间件，因为只有请求<code>/user/list</code>的时候，才会调用该中间件。</p>
<p>也可以同时使用多个局部中间件，比如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> mw1 = <span class="function"><span class="keyword">function</span>(<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;我是第1个局部中间件！&quot;</span>);</span><br><span class="line">    next();</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">const</span> mw2 = <span class="function"><span class="keyword">function</span>(<span class="params">req,res,next</span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;我是第2个局部中间件！&quot;</span>);</span><br><span class="line">    next();</span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// 挂载路由</span></span><br><span class="line">router.get(<span class="string">&#x27;/users/list&#x27;</span>,[mw1,mw2],<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    response.send(<span class="string">&#x27;Get user list.&#x27;</span>)</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>或者使用如下方法</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">router.get(<span class="string">&#x27;/users/list&#x27;</span>,mw1,mw2,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    response.send(<span class="string">&#x27;Get user list.&#x27;</span>)</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line">router.get(<span class="string">&#x27;/users/list&#x27;</span>,[mw1,mw2],<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    response.send(<span class="string">&#x27;Get user list.&#x27;</span>)</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>这里我们定义了两个局部中间件，都可以在这里一次性使用。打印结果如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">这也是一个中间件函数！			 //全局中间件</span><br><span class="line">我是第1个局部中间件！			 //局部中间件1</span><br><span class="line">我是第2个局部中间件！			 //局部中间件2</span><br></pre></td></tr></table></figure>

<h2 id="10-中间件的5个使用注意事项"><a href="#10-中间件的5个使用注意事项" class="headerlink" title="10.中间件的5个使用注意事项"></a>10.中间件的5个使用注意事项</h2><ol>
<li><strong>一定要在路由之前注册中间件，（路由可以理解为最后一个中间件【除了错误级别中间件】）</strong></li>
<li><strong>客户端发送过来的请求，可以连续调用多个中间件进行处理</strong></li>
<li><strong>执行完中间件的业务代码之后，不要忘记调用next()函数进行处理</strong></li>
<li><strong>为了防止逻辑代码混乱，调用next()函数之后不要再写额外的代码</strong></li>
<li><strong>连续调用多个中间件时，多个中间件之间，共享req和res</strong></li>
</ol>
<h2 id="11-中间件的分类"><a href="#11-中间件的分类" class="headerlink" title="11.中间件的分类"></a>11.中间件的分类</h2><p>Express为了使用者方便，把常见的中间件用法分成了5大类</p>
<ol>
<li>应用级别中间件            通过app.use或者app.get/app.post等绑定到app实例上的中间件如 app.use(mw1)        </li>
<li>路由级别中间件            绑定到express.Router()实例上的中间件，router.get(mw1)等</li>
<li>错误级别中间件            用来捕获整个项目中发生异常的中间件，放在路由的后面。</li>
<li>Express内置中间件     内置的一些中间件，比如querystring等</li>
<li>第三方中间件                第三方开发者提供的中间件</li>
</ol>
<h2 id="12-错误级别中间件"><a href="#12-错误级别中间件" class="headerlink" title="12.错误级别中间件"></a>12.错误级别中间件</h2><p>错误级别的中间件的作用：用来捕获整个项目中发生异常的中间件，从而防止项目异常奔溃的问题，放在路由的后面。</p>
<p>格式：错误级别中间件的function处理函数中，必须有4个形参，从前到后，分别是(err,req,res,next)，格式如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function">(<span class="params">err, req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">    res.send(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>使用：</p>
<p>在路由的模块的某个请求中，手动写一个异常</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">router.get(<span class="string">&#x27;/users/list&#x27;</span>,mw1,mw2,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">&quot;服务器内部发生错误&quot;</span>);</span><br><span class="line">    response.send(<span class="string">&#x27;Get user list.&#x27;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>如果不写错误类型中间件进行异常捕获，那么发送本次请求，就会导致程序崩溃，如下</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/error.png" class title="无错误级别中间件出现异常时导致程序崩溃">

<p>在app.js模块中，注册错误级别的中间件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//app.js</span></span><br><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line"></span><br><span class="line">app.use(<span class="function">(<span class="params">req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;这也是一个中间件函数！&quot;</span>);</span><br><span class="line">    next();</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">app.get(<span class="string">&#x27;/&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;调用了 / 路由&quot;</span>);</span><br><span class="line">    res.send(<span class="string">&#x27;Home page&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">app.get(<span class="string">&#x27;/user&#x27;</span>, <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;调用了 /user 路由&quot;</span>);</span><br><span class="line">    res.send(<span class="string">&#x27;User page&#x27;</span>);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">app.use(router);</span><br><span class="line"></span><br><span class="line">app.use(<span class="function">(<span class="params">err, req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">    res.send(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/error_catch.png" class title="添加错误级别中间件出现异常时程序不会崩溃而抛出异常">

<p><strong>注意：错误级别的中间件，应该放在所有路由之后，这样才能捕获到所有异常，且不需要next()，因为已经把错误类型抛出了</strong></p>
<h2 id="13-Express内置中间件（json-urlencoded）"><a href="#13-Express内置中间件（json-urlencoded）" class="headerlink" title="13.Express内置中间件（json,urlencoded）"></a>13.Express内置中间件（json,urlencoded）</h2><p>最基本的3个内置中间件</p>
<p>1.express.static()快速托管静态资源</p>
<p>2.express.json(),将json格式的请求体数据解析出来（在4.16.0+版本可用）</p>
<p>3.express.urlencoded()解析url-encoded格式的请求体数据（在4.16.0+版本可用）</p>
<p>使用方式如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">app.use(express.json());</span><br><span class="line">app.use(express.urlencoded(&#123; <span class="attr">extended</span>: <span class="literal">false</span> &#125;));</span><br></pre></td></tr></table></figure>

<p>比如，当我们用post请求提交一个json数据时，在postman我们这么做</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman.png" class title="试图用postman提交一个json格式的请求体数据">

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">router.post(<span class="string">&#x27;/user/add&#x27;</span>,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(request.body);			<span class="comment">//undefined</span></span><br><span class="line">    response.send(<span class="string">&#x27;Add new user&#x27;</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>当我们使用了app.use(express.json())中间件进行解析之后</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line">app.use(express.json());</span><br><span class="line"><span class="comment">// app.use(express.urlencoded(&#123; extended: false &#125;));</span></span><br><span class="line"></span><br><span class="line">app.use(router);</span><br><span class="line">app.use(<span class="function">(<span class="params">err, req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">    res.send(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>同一个请求，结果如下：</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">router.post(<span class="string">&#x27;/user/add&#x27;</span>,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(request.body);			<span class="comment">// &#123; name: &#x27;zhangsan&#x27;, age: 20, gender: &#x27;女&#x27; &#125;</span></span><br><span class="line">    response.send(<span class="string">&#x27;Add new user&#x27;</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman1.png" class title="添加了json解析请求体之后用postman提交一个json格式的请求">

<p>当我们使用xxx-form-urlencoded的格式去提交一个请求时，</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman2.png" class title="试图用postman提交一个xxx-form-urlencoded的格式的请求体数据">

<p>如果不使用解析，那么得到的结果是</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">router.post(<span class="string">&#x27;/user/add&#x27;</span>,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(request.body);			<span class="comment">// &#123;&#125;</span></span><br><span class="line">    response.send(<span class="string">&#x27;Add new user&#x27;</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>此时，如果我们使用Express内置的中间件去处理urlencoded格式的请求体数据</p>
<p>固定格式：<code>app.use(express.urlencoded(&#123; extended: false &#125;));</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line">app.use(express.json());</span><br><span class="line">app.use(express.urlencoded(&#123; <span class="attr">extended</span>: <span class="literal">false</span> &#125;));</span><br><span class="line"></span><br><span class="line">app.use(router);</span><br><span class="line">app.use(<span class="function">(<span class="params">err, req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">    res.send(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>得到的结果如下：</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman3.png" class title="添加了urlencoded解析请求体之后用postman提交一个urlencoded格式的请求">

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">router.post(<span class="string">&#x27;/user/add&#x27;</span>,<span class="function">(<span class="params">request,response</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(request.body);	  <span class="comment">//[Object: null prototype] &#123; first_name: &#x27;张三&#x27;, last_name: &#x27;李四&#x27; &#125;</span></span><br><span class="line">    response.send(<span class="string">&#x27;Add new user&#x27;</span>)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h2 id="14-自定义中间件"><a href="#14-自定义中间件" class="headerlink" title="14.自定义中间件"></a>14.自定义中间件</h2><p>手动模拟一个类似于express.urlencoded这样的中间件，来解析POST提交到服务器的表单数据</p>
<p>实现步骤</p>
<ol>
<li>定义中间件</li>
<li>监听req的data事件</li>
<li>监听req的end事件</li>
<li>使用querystring模块来解析请求体数据</li>
<li>将解析出来的数据对象挂载为req.body</li>
<li>将自定义中间件封装为模块</li>
</ol>
<p>开始：</p>
<p>在中间件中，需要监听req对象的data事件，来获取客户端发送到服务器的数据</p>
<p>如果数据量比较大，无法一次性发送完毕，则客户端会把数据分割后，分批发送到服务器，所以data事件可能会出发多次，每一次触发data事件时，获取到数据只是完整数据的一部分，需要手动把接收到的数据进行拼接。</p>
<p>当数据接收完毕之后，就会触发req的end事件，因此我们可以在req的end事件中，拿到并处理完整请求体数据。</p>
<p>postman请求</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman4.png" class title="用postman提交一个urlencoded格式的请求">

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function">(<span class="params">req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 定义中间件具体的业务逻辑</span></span><br><span class="line">    <span class="comment">// 定义一个字符串，用来存储客户端发送过来的请求体</span></span><br><span class="line">    <span class="keyword">let</span> str = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="comment">// 监听req的data事件</span></span><br><span class="line">    req.on(<span class="string">&#x27;data&#x27;</span>, <span class="function">(<span class="params">chunck</span>) =&gt;</span> &#123;</span><br><span class="line">        str += chunck;</span><br><span class="line">    &#125;)</span><br><span class="line">    req.on(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;客户端发过来的数据&quot;</span> + str);	</span><br><span class="line">        <span class="comment">//客户端发过来的数据first_name=%E5%BC%A0%E4%B8%89&amp;last_name=%E6%9D%8E%E5%9B%9B</span></span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman5.png" class title="服务端拿到客户端发过来的数据">

<p>此时可以看到，我们需要把该字符串解析成对象的形式，需要使用querystring方法来从字符串解析成对象</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function">(<span class="params">req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 定义中间件具体的业务逻辑</span></span><br><span class="line">    <span class="comment">// 定义一个字符串，用来存储客户端发送过来的请求体</span></span><br><span class="line">    <span class="keyword">let</span> str = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="comment">// 监听req的data事件</span></span><br><span class="line">    req.on(<span class="string">&#x27;data&#x27;</span>, <span class="function">(<span class="params">chunck</span>) =&gt;</span> &#123;</span><br><span class="line">        str += chunck;</span><br><span class="line">    &#125;)</span><br><span class="line">    req.on(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;客户端发过来的数据&quot;</span> + str);</span><br><span class="line">        <span class="comment">// 把字符串转化为对象</span></span><br><span class="line">        <span class="keyword">const</span> body = querystring.parse(str);</span><br><span class="line">        <span class="comment">// [Object: null prototype] &#123; first_name: &#x27;张三&#x27;, last_name: &#x27;李四&#x27; &#125;</span></span><br><span class="line">        <span class="built_in">console</span>.log(body)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman6.png" class title="服务端拿到客户端发过来的字符串转化为对象">

<p>querystring这个方法已经被弃用了，The <code>querystring</code> API is considered Legacy. While it is still maintained, new code should use the <code>URLSearchParams</code> API instead. 后续可能不再支持。以后改用<strong>URLSearchParams</strong>方法</p>
<p>可以按住ctrl点击querystring进入源码，然后删除<code>*@disprecated legacy</code>这一行代码，就不会被画横线删掉了（治标不治本，建议用新的API）</p>
<p>最后把body属性动态的挂载到req上</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">app.use(<span class="function">(<span class="params">req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 定义中间件具体的业务逻辑</span></span><br><span class="line">    <span class="comment">// 定义一个字符串，用来存储客户端发送过来的请求体</span></span><br><span class="line">    <span class="keyword">let</span> str = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="comment">// 监听req的data事件</span></span><br><span class="line">    req.on(<span class="string">&#x27;data&#x27;</span>, <span class="function">(<span class="params">chunck</span>) =&gt;</span> &#123;</span><br><span class="line">        str += chunck;</span><br><span class="line">    &#125;)</span><br><span class="line">    req.on(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;客户端发过来的数据&quot;</span> + str);</span><br><span class="line">        <span class="comment">// 把字符串转化为对象</span></span><br><span class="line">        <span class="keyword">const</span> body = querystring.parse(str);</span><br><span class="line">        req.body = body;</span><br><span class="line">        next()</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman7.png" class title="服务端拿到客户端发过来的字符串转化为对象并返回客户端">

<p><strong>将这个中间件封装为模块</strong></p>
<p>新建一个querystring.js的文件</p>
<p>且把该方法暴露出来，则</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> queryString = <span class="built_in">require</span>(<span class="string">&#x27;querystring&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> querystring = <span class="function">(<span class="params">req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 定义中间件具体的业务逻辑</span></span><br><span class="line">    <span class="comment">// 定义一个字符串，用来存储客户端发送过来的请求体</span></span><br><span class="line">    <span class="keyword">let</span> str = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    <span class="comment">// 监听req的data事件</span></span><br><span class="line">    req.on(<span class="string">&#x27;data&#x27;</span>, <span class="function">(<span class="params">chunck</span>) =&gt;</span> &#123;</span><br><span class="line">        str += chunck;</span><br><span class="line">    &#125;)</span><br><span class="line">    req.on(<span class="string">&#x27;end&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;客户端发过来的数据&quot;</span> + str);</span><br><span class="line">        <span class="comment">// 把字符串转化为对象</span></span><br><span class="line">        <span class="keyword">const</span> body = queryString.parse(str);</span><br><span class="line">        req.body = body;</span><br><span class="line">        next()</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = querystring;</span><br></pre></td></tr></table></figure>

<p>在app.js中使用自定义的中间件</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> express = <span class="built_in">require</span>(<span class="string">&#x27;express&#x27;</span>);</span><br><span class="line"><span class="comment">// 导入写好的路由模块</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="built_in">require</span>(<span class="string">&#x27;./router&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> qc = <span class="built_in">require</span>(<span class="string">&#x27;./querystring&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> app = express();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用自定义的中间件</span></span><br><span class="line">app.use(qc)</span><br><span class="line">app.use(router);</span><br><span class="line">app.use(<span class="function">(<span class="params">err, req, res, next</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">    res.send(<span class="string">&#x27;Error:&#x27;</span> + err.message);</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 监听8008端口</span></span><br><span class="line">app.listen(<span class="number">8008</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;app is running http://127.0.0.1:8008&quot;</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>结果如下</p>
<img src="/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/postman8.png" class title="服务端拿到客户端发过来的字符串转化为对象并返回客户端">

      
    </div>
    
    
    

    

    
      <div>
        <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
  <div>坚持原创技术分享，您的支持将鼓励我继续创作！</div>
  <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
    <span>打赏</span>
  </button>
  <div id="QR" style="display: none;">

    
      <div id="wechat" style="display: inline-block">
        <img id="wechat_qr" src="http://chaoyxy.cn/data/User/admin/home/desktop/images/alipay.jpg" alt=" 微信支付"/>
        <p>微信支付</p>
      </div>
    

    
      <div id="alipay" style="display: inline-block">
        <img id="alipay_qr" src="http://chaoyxy.cn/data/User/admin/home/desktop/images/wechatpay.jpg" alt=" 支付宝"/>
        <p>支付宝</p>
      </div>
    

    

  </div>
</div>

      </div>
    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/blogs/tags/Node-js/" rel="tag"># Node.js</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blogs/2022/04/25/express%E7%9A%84%E6%A8%A1%E5%9D%97%E5%8C%96%E8%B7%AF%E7%94%B1/" rel="next" title="express的模块化路由">
                <i class="fa fa-chevron-left"></i> express的模块化路由
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blogs/2022/04/28/Express%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81/" rel="prev" title="Express身份认证">
                Express身份认证 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  
    <div class="comments" id="comments">
      <div id="disqus_thread">
        <noscript>
          Please enable JavaScript to view the
          <a target="_blank" rel="noopener" href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a>
        </noscript>
      </div>
    </div>

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image"
                src="/blogs/images/cat.jpg"
                alt="" />
            
              <p class="site-author-name" itemprop="name"></p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blogs/archives">
              
                  <span class="site-state-item-count">43</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/blogs/tags/index.html">
                  <span class="site-state-item-count">10</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          
            <div class="links-of-author motion-element">
                
                  <span class="links-of-author-item">
                    <a href="https://gitee.com/louchaoyy" target="_blank" title="Gitee">
                      
                        <i class="fa fa-fw fa-gitee"></i>Gitee</a>
                  </span>
                
                  <span class="links-of-author-item">
                    <a href="louchao@louchaoyy.cn" target="_blank" title="E-Mail">
                      
                        <i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                  </span>
                
            </div>
          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#Express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6%EF%BC%88%E7%AC%94%E8%AE%B0%EF%BC%89"><span class="nav-number">1.</span> <span class="nav-text">Express之中间件（笔记）</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-Express%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E8%B0%83%E7%94%A8%E6%B5%81%E7%A8%8B"><span class="nav-number">1.1.</span> <span class="nav-text">1.Express中间件的调用流程</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-Express%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E6%A0%BC%E5%BC%8F"><span class="nav-number">1.2.</span> <span class="nav-text">2.Express中间件的格式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-next%E5%87%BD%E6%95%B0%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-number">1.3.</span> <span class="nav-text">3.next函数的作用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E5%AE%9A%E4%B9%89%E4%B8%AD%E9%97%B4%E4%BB%B6%E5%87%BD%E6%95%B0"><span class="nav-number">1.4.</span> <span class="nav-text">4.定义中间件函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E5%85%A8%E5%B1%80%E7%94%9F%E6%95%88%E7%9A%84%E4%B8%AD%E9%97%B4%E4%BB%B6"><span class="nav-number">1.5.</span> <span class="nav-text">5.全局生效的中间件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#6-%E5%85%A8%E5%B1%80%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E7%AE%80%E5%8C%96%E5%BD%A2%E5%BC%8F"><span class="nav-number">1.6.</span> <span class="nav-text">6.全局中间件的简化形式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#7-%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-number">1.7.</span> <span class="nav-text">7.中间件的作用</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#8-%E8%BF%9E%E7%BB%AD%E5%AE%9A%E4%B9%89%E5%A4%9A%E4%B8%AA%E5%85%A8%E5%B1%80%E4%B8%AD%E9%97%B4%E4%BB%B6"><span class="nav-number">1.8.</span> <span class="nav-text">8.连续定义多个全局中间件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#9-%E5%B1%80%E9%83%A8%E7%94%9F%E6%95%88%E7%9A%84%E4%B8%AD%E9%97%B4%E4%BB%B6"><span class="nav-number">1.9.</span> <span class="nav-text">9.局部生效的中间件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#10-%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%845%E4%B8%AA%E4%BD%BF%E7%94%A8%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9"><span class="nav-number">1.10.</span> <span class="nav-text">10.中间件的5个使用注意事项</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E5%88%86%E7%B1%BB"><span class="nav-number">1.11.</span> <span class="nav-text">11.中间件的分类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#12-%E9%94%99%E8%AF%AF%E7%BA%A7%E5%88%AB%E4%B8%AD%E9%97%B4%E4%BB%B6"><span class="nav-number">1.12.</span> <span class="nav-text">12.错误级别中间件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#13-Express%E5%86%85%E7%BD%AE%E4%B8%AD%E9%97%B4%E4%BB%B6%EF%BC%88json-urlencoded%EF%BC%89"><span class="nav-number">1.13.</span> <span class="nav-text">13.Express内置中间件（json,urlencoded）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#14-%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%AD%E9%97%B4%E4%BB%B6"><span class="nav-number">1.14.</span> <span class="nav-text">14.自定义中间件</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      
        <div class="back-to-top">
          <i class="fa fa-arrow-up"></i>
          
        </div>
      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<div class="copyright">&copy; <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Chaoyxy</span>

  
</div>

<span id="busuanzi_container_site_pv">
    本站总访问量<span id="busuanzi_value_site_pv"></span>次
</span>
<!--

  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.3</div>
-->




        







        
      </div>
    </footer>

    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/blogs/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blogs/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blogs/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blogs/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blogs/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blogs/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="/blogs/lib/canvas-nest/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/blogs/js/src/utils.js?v=5.1.3"></script>

  <script type="text/javascript" src="/blogs/js/src/motion.js?v=5.1.3"></script>



  
  


  <script type="text/javascript" src="/blogs/js/src/affix.js?v=5.1.3"></script>

  <script type="text/javascript" src="/blogs/js/src/schemes/pisces.js?v=5.1.3"></script>



  
  <script type="text/javascript" src="/blogs/js/src/scrollspy.js?v=5.1.3"></script>
<script type="text/javascript" src="/blogs/js/src/post-details.js?v=5.1.3"></script>



  


  <script type="text/javascript" src="/blogs/js/src/bootstrap.js?v=5.1.3"></script>



  


  

    
      <script id="dsq-count-scr" src="https://Chaoyxy.disqus.com/count.js" async></script>
    

    
      <script type="text/javascript">
        var disqus_config = function () {
          this.page.url = 'https://louchaoyy.gitee.io/blogs/2022/04/25/express%E4%B9%8B%E4%B8%AD%E9%97%B4%E4%BB%B6/';
          this.page.identifier = '2022/04/25/express之中间件/';
          this.page.title = 'express之中间件';
        };
        var d = document, s = d.createElement('script');
        s.src = 'https://Chaoyxy.disqus.com/embed.js';
        s.setAttribute('data-timestamp', '' + +new Date());
        (d.head || d.body).appendChild(s);
      </script>
    

  




	





  














  





  

  

  

  
  

  

  

  

</body>
</html>
